﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace DARE
{
    #if !WINDOWS_PHONE
    /// <summary>
    /// This represents a video. This widget allows to play a video on the HUD.
    /// To play a video just call the Init() method with the name of the video asset name.
    /// </summary>
    [AttrTypeDependentSerializable(typeof(CVideoPanelData))]
    public class CVideoPanel : CWidget
    {
        #region fields

        private VideoPlayer m_vp = null;
        private bool m_isInit;
        private bool m_isLooped = false;
        private Rectangle m_videoRect;
        private Texture2D m_backgroundTexture;
        private string m_videoName;

        #endregion

        #region properties

        /// <summary>
        /// Gets/Sets the volume of the video
        /// </summary>
        public float Volume { get { return m_vp.Volume; } set { m_vp.Volume = value; } }

        /// <summary>
        /// Gets the Video
        /// </summary>
        public Video Video
        {
            get { if (m_vp != null) return m_vp.Video; return null; }
        }

        /// <summary>
        /// Gets the name of the video being played or sets the video to be played.
        /// </summary>
        public string VideoToPlay
        {
            get { return m_videoName; }
            set { m_videoName = value; Init(m_videoName); }
        }

        /// <summary>
        /// Gets/Sets the VideoPlayer
        /// </summary>
        public VideoPlayer Player { get { return m_vp; } set { m_vp = value; } }

        /// <summary>
        /// Gets/Sets the loop states. If this value is set to true, the video will be played in loops.
        /// </summary>
        public bool IsLooped { get { m_isLooped = m_vp.IsLooped; return m_isLooped; } set { m_isLooped = value; m_vp.IsLooped = value; } }

        /// <summary>
        /// Gets the curent video frame
        /// </summary>
        public Texture2D VideoTexture
        {
            get { if (m_vp != null) return m_vp.GetTexture(); return null; }
        }

        /// <summary>
        /// If the value is between 0 and 1, the size is a percentage of the size of the parent
        /// (if the parent is null, the value is a percentage of the window).
        /// Else, the value is absolute.
        /// </summary>
        public override Vector2 Size
        {
            get
            {
                return base.Size;
            }
            set
            {
                base.Size = value;
                Actualize();
            }
        }

        /// <summary>
        /// If the value is between 0 and 1, the position is a percentage of the size of the parent
        /// (if the parent is null, the value is a percentage of the window).
        /// The value is relative to its parent.
        /// </summary>
        public override Vector2 Position
        {
            get
            {
                return base.Position;
            }
            set
            {
                base.Position = value;
                Actualize();
            }
        }

        /// <summary>
        /// Gets/Sets the rectangle where the widget will be draw.
        /// This value is automatically set when the position and/or the size are set.
        /// If you plan to use a different rectangle than the one automatically created,
        /// we recommand you to use the UseDrawableRect and DrawableRect properties.
        /// </summary>
        /// <seealso cref="UseDrawableRect"/>
        /// <seealso cref="DrawableRect"/>
        public override Rectangle Rect
        {
            get
            {
                return base.Rect;
            }
            set
            {
                base.Rect = value;
                Actualize();
            }
        }

        #endregion

        #region actualize

        /// <summary>
        /// Actualizes the widget.
        /// If anything has changed, it will allow this widget to get back its parameters.
        /// For example, if the size of the widget is a percentage of the size of its parent,
        /// if the parent's size changes, it will recalculate the good size of this widget.
        /// (This method is called automatically but you can force a new actualization).
        /// </summary>
        public override void Actualize()
        {
            if (m_rect == null)
                m_rect = new Rectangle();
            if (m_parent != null)
                this.m_parent.giveSubRect(m_position, m_size, ref m_rect);
            int width;
            int height;
            if (m_rect.Width < m_rect.Height)
            {
                width = m_rect.Width;
                height = m_vp.Video.Height * width / m_vp.Video.Width;
            }
            else
            {
                width = m_vp.Video.Width * m_rect.Height / m_vp.Video.Height;
                height = m_rect.Height;
            }
            if (m_videoRect == null)
                m_videoRect = new Rectangle();
            m_videoRect.X = (int)(m_rect.X + ((m_rect.Width / 2.0f) - (width / 2.0f)));
            m_videoRect.Y = (int)(m_rect.Y + ((m_rect.Height / 2.0f) - (height / 2.0f)));
            m_videoRect.Width = width;
            m_videoRect.Height = height;
            foreach (CWidget child in m_children.Values)
                child.Actualize();
        }


        #endregion

        #region ctor

        public CVideoPanel(CHUDSystem hud, CWidget parent, string name)
            : base(hud, parent, name)
        {
            m_vp = new VideoPlayer();
            m_isInit = false;
            m_texture = new CHudTexture();
            m_texture.SpriteBatch = hud.SpriteBatch;
            Size = new Vector2(200, 200);
        }

        #endregion

        #region play video

        /// <summary>
        /// Initializes and starts the video given in parameters.
        /// </summary>
        /// <param name="videoName"></param>
        public void Init(string videoName)
        {
            Video vid = CResourceMgr.Load<Video>(videoName);
            if (vid == null)
                return;
            m_videoName = videoName;
            m_vp.Play(vid);
            m_backgroundTexture = new Texture2D(Game.GraphicsDevice, 10, 10);
            Actualize();
            Color = Color.Black;
            m_isInit = true;
        }

        #endregion

        #region update

        public override bool Update(GameTime gameTime)
        {
            base.Update(gameTime);
            if (!m_isInit)
                return false;
            m_texture.Body = m_vp.GetTexture();
            m_texture.Rectangle = m_rect;
            return true;
        }

        #endregion

        #region draw

        public override bool Draw(GameTime gameTime)
        {
            if (m_texture.Body == null)
                m_texture.Body = m_vp.GetTexture();
            SpriteBatch.End();
            SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque);
            SpriteBatch.Draw(m_backgroundTexture, m_rect, Color.Black);

            if (m_texture.Body != null)
                m_texture.Draw(gameTime);
            //m_spriteBatch.Draw(m_texture, m_videoRect, Color.White);
            SpriteBatch.End();
            SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullCounterClockwise, HUD.Shader);
            foreach (CWidget child in m_children.Values)
                child.Draw(gameTime);
            return true;
        }

        #endregion
    }
#endif
}
